package com.utilities.parsers;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

import com.utilities.IO.FileUtilities;
import com.utilities.parsers.ContigParser.ParseAllContigsFileParser;
import com.utilities.parsers.ContigParser.ParseEvents;
import com.utilities.parsers.ContigParser.ParseListener;

public class contigParser extends ParseListener{

	private FileWriter fw = null;
	private int endIndex = 1;
	private String contigName = null;
	private StringBuffer buffer = new StringBuffer();
	private int count = 0;
	private ArrayList<String> gapinFo = new ArrayList<String>();
	private int maxGapIndex = -1;
	private int minGapIndex = -1;
	private FileWriter fw2 = null;
	private int gapCounter = 0;
	private ArrayList<String> contiginFo = new ArrayList<String>();
	private int contigLengthCounter = 0;
	private int gapLengthCounter = 0;
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception
	{
		args = new String[3];
		args[0] = "c:/database/latest/70_scaffold.fna";
		args[1] = "c:/database/latest/70_gaps.fna";
		args[2] = "c:/database/latest/70.fna";
		contigParser contigParser = new contigParser();
		contigParser.fw = new FileWriter(new File(args[0]));
		contigParser.fw2 = new FileWriter(new File(args[1]));
		ParseAllContigsFileParser allContigsFileParser = 
			new ParseAllContigsFileParser();
		allContigsFileParser.addListener(contigParser);
		allContigsFileParser.parse(new FileReader(args[2]));
//		contigParser.gapinFo.add("Number of gaps " + contigParser.gapCounter);
//		contigParser.gapinFo.add(String.format("Max gap : %s", contigParser.gapinFo.get(contigParser.maxGapIndex)));
//		contigParser.gapinFo.add(String.format("Min gap : %s", contigParser.gapinFo.get(contigParser.minGapIndex)));
//		contigParser.gapinFo.add("Scaffold length " + contigParser.count);
		
		Collections.sort(contigParser.contiginFo, contigParser.new GapInfoComparator());
		int lgth = contigParser.contigLengthCounter;
		for (int i = contigParser.contiginFo.size() - 1; i >= 0 ; i--)
		{
			String info = contigParser.contiginFo.get(i);
			Scanner scanner = new Scanner(info);
			scanner.useDelimiter(" length is ");
			scanner.next();
			int templength = Integer.parseInt(scanner.next());
			lgth = lgth - templength;
			if (lgth < contigParser.contigLengthCounter / 2)
			{
				contigParser.gapinFo.add("Mean contig length " + info);
				break;
			}
		}
		contigParser.gapinFo.add("number of contigs " + contigParser.contiginFo.size());
		contigParser.gapinFo.add("Total Contig Length " + contigParser.contigLengthCounter);
		contigParser.gapinFo.add("Total Gap length " + contigParser.gapLengthCounter);
		FileUtilities.writeToFile(contigParser.gapinFo, "c:/database/454/7328Run1_scaffold.info");
	}

	public void handleEvent(ParseEvents event) 
	{
		try
		{
			switch((ParseEvents.EventTypes)event.getEventType())
			{
				case docEnded : write(); fw.close(); fw2.flush(); fw2.close(); System.out.println(" end reading " + contigName); break; 
				case docStarted: 
					{
						fw.write(">Scaffold\n");
						break;
					}
				case contigStarted: 
				{
					if (endIndex != 1)
					{
						System.out.println(" end reading " + contigName);
					}
					
					String str = (String)event.getSource();
					String[] params = str.split(" ");
					contigName = params[0].split(">")[1];
					System.out.print("started reading " + contigName);
					int newStartIndex = 0;
					for (String param : params)
					{
						if (param.contains(".."))
						{
							newStartIndex = Integer.parseInt(param.split("[..]")[0].trim());
							
							if (endIndex < newStartIndex)
							{
//								if (endIndex != 1)
//								{
									int length = newStartIndex - endIndex - 1;
									gapinFo.add(String.format("gap found: %s..%s length is %s", endIndex + 1, newStartIndex - 1, length));
									fw2.write(String.format(">gap%s %s..%s\n", gapCounter, endIndex + 1, newStartIndex - 1));
									gapCounter++;
									if (gapinFo.size() == 1)
									{
										maxGapIndex = 0;
										minGapIndex = 0;
									}
									else
									{
										Scanner scanner = new Scanner(gapinFo.get(maxGapIndex));
										scanner.useDelimiter(" length is ");
										scanner.next();
										int maxlength = Integer.parseInt(scanner.next());
										if (length > maxlength ) maxGapIndex = gapinFo.size() - 1;
										
										scanner = new Scanner(gapinFo.get(minGapIndex));
										scanner.useDelimiter(" length is ");
										scanner.next();
										int minlength = Integer.parseInt(scanner.next());
										if (length < minlength ) minGapIndex = gapinFo.size() - 1;
									}
//								}
								gapLengthCounter = gapLengthCounter + newStartIndex - endIndex; 
								writeToBuffer(null, newStartIndex - endIndex);
							}
							else
							{
								System.out.println("Complement found at : " + contigName);
							}
							endIndex = Integer.parseInt(param.split("[..]")[2].trim());
							contiginFo.add(String.format("contig found: %s..%s length is %s", newStartIndex, 
									endIndex, endIndex - newStartIndex + 1));
							contigLengthCounter = contigLengthCounter + endIndex - newStartIndex + 1;
							break;
						}
					}
					break;
				}
				case seqread : 
				{
					String str = ((String)event.getSource()).trim();
					writeToBuffer(str,str.length());
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	private void write() throws Exception
	{
		for (int i = 0 ; i<buffer.length() ; i++)
		{
			fw.append(buffer.charAt(i));
			count++;
			if (count%60 == 0)
			{
				fw.append("\n");
			}
		}
		buffer = new StringBuffer();
		fw.flush();
	}

	private void writeToBuffer(String str, int i) throws Exception 
	{
		if (str == null)
		{
			for (int j = 0 ; j < i ; j++)
			{
				buffer.append('N');
			}
		}
		else
		{
			buffer.append(str);
		}
		
		if (buffer.length() > 500)
		{
			write();
		}
	}
	
	class GapInfoComparator implements Comparator<String>
	{

		@Override
		public int compare(String o1, String o2) {
			Scanner scanner = new Scanner(o1);
			scanner.useDelimiter(" length is ");
			scanner.next();
			int o1Length = Integer.parseInt(scanner.next());
			
			scanner = new Scanner(o2);
			scanner.useDelimiter(" length is ");
			scanner.next();
			int o2Length = Integer.parseInt(scanner.next());
			
			return o1Length - o2Length;
		}
		
	}
} // contigParser
